﻿
namespace Anycmd.Host
{
    using AC.Identity;
    using Anycmd.AC;
    using Impl;
    using Model;
    using Repositories;
    using System;
    using System.Security.Principal;

    /// <summary>
    /// 表示用户会话业务实体。
    /// </summary>
    public class UserSessionState : IUserSession, IStateObject
    {
        public static readonly UserSessionState Empty = new UserSessionState
        {
            Host = EmptyACDomain.SingleInstance,
            Principal = new AnycmdPrincipal(EmptyACDomain.SingleInstance, new UnauthenticatedIdentity()),
            Account = AccountState.Empty,
            Id = Guid.Empty
        };

        private readonly Guid _accountID;
        private AccountState _account;
        private AccountPrivilege _accountPrivilege;

        private UserSessionState()
        {

        }

        internal UserSessionState(IACDomain host, Guid sessionID, IPrincipal principal, AccountState account)
        {
            if (host == null)
            {
                throw new ArgumentNullException("host");
            }
            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }
            if (account == null)
            {
                throw new ArgumentNullException("account");
            }
            this.Host = host;
            this.Id = sessionID;
            this.Principal = principal;
            this.Account = account;
            this._accountID = account.Id;
        }

        internal UserSessionState(IACDomain host, UserSessionBase userSessionEntity)
        {
            if (host == null)
            {
                throw new ArgumentNullException("host");
            }
            if (userSessionEntity == null)
            {
                throw new ArgumentNullException("userSessionEntity");
            }
            var principal = new AnycmdPrincipal(host, new AnycmdIdentity(userSessionEntity.AuthenticationType, userSessionEntity.IsAuthenticated, userSessionEntity.LoginName));
            this.Host = host;
            this.Id = userSessionEntity.Id;
            this.Principal = principal;
            this._accountID = userSessionEntity.AccountID;
        }

        public IACDomain Host { get; private set; }

        public Guid Id { get; private set; }

        public IPrincipal Principal { get; private set; }

        public AccountPrivilege AccountPrivilege
        {
            get
            {
                if (_accountPrivilege == null)
                {
                    _accountPrivilege = new AccountPrivilege(this.Host, this._accountID);
                    string msg;
                    if (!Host.DSDSetSet.CheckRoles(_accountPrivilege.AuthorizedRoles, out msg))
                    {
                        throw new Exceptions.ValidationException(msg);
                    }
                }
                return _accountPrivilege;
            }
        }

        /// <summary>
        /// 工人
        /// </summary>
        public AccountState Account
        {
            get
            {
                if (_account == null)
                {
                    var accountRepository = Host.GetRequiredService<IRepository<Account>>();
                    _account = AccountState.Create(accountRepository.GetByKey(this._accountID));
                }
                return _account;
            }
            private set { _account = value; }
        }
    }
}
